package com.novel.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.novel.core.common.constant.ErrorCodeEnum;
import com.novel.core.common.exception.BusinessException;
import com.novel.core.common.req.AdminPageReqDto;
import com.novel.core.common.resp.PageRespDto;
import com.novel.core.common.resp.RestResp;
import com.novel.core.constant.SystemConfigConsts;
import com.novel.core.util.JwtUtils;
import com.novel.dto.req.AdminLoginReqDto;
import com.novel.dto.req.AuthorInfoReqDto;
import com.novel.dto.req.BookListRepDto;
import com.novel.dto.req.UserInfoReqDto;
import com.novel.dto.resp.*;
import com.novel.entity.*;
import com.novel.mapper.*;
import com.novel.service.AdminService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author wang
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AdminServiceImpl implements AdminService {

    private final AdminMapper adminMapper;

    private final BookCategoryMapper bookCategoryMapper;

    private final AuthorInfoMapper authorInfoMapper;

    private final UserInfoMapper userInfoMapper;

    private final BookInfoMapper bookInfoMapper;

    private final JwtUtils jwtUtils;

    @Override
    public RestResp<AdminLoginRespDto> login(AdminLoginReqDto loginReqDto) {
        LambdaQueryWrapper<Admin> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        lambdaQueryWrapper.eq(Admin::getUsername, loginReqDto.getUsername());
        Admin admin = adminMapper.selectOne(lambdaQueryWrapper);

        // 判断用户是否存在
        if (Objects.isNull(admin)) {
            // 用户不存在
            throw new BusinessException(ErrorCodeEnum.USER_ACCOUNT_NOT_EXIST);
        }
        // 判断密码是否正确
        if (!Objects.equals(admin.getPassword(), DigestUtils.md5DigestAsHex(loginReqDto.getPassword().getBytes(StandardCharsets.UTF_8)))){
            // 密码错误
            throw new BusinessException(ErrorCodeEnum.USER_PASSWORD_ERROR);
        }

        // 登录成功，生成JWT并返回
        return RestResp.ok(AdminLoginRespDto.builder()
                .uid(admin.getId())
                .token(jwtUtils.generateToken(admin.getId(), SystemConfigConsts.NOVEL_ADMIN_KEY))
                .type(admin.getType())
                .name(admin.getName()).build());
    }

    @Override
    public RestResp<List<BookCategoryRespDto>> getBookCategory() {
        List<BookCategory> bookCategories = bookCategoryMapper.selectList(null);
        List<BookCategoryRespDto> list = new ArrayList<>();
        for(BookCategory bookCategory: bookCategories) {
            list.add(BookCategoryRespDto.builder().id(bookCategory.getId()).name(bookCategory.getName()).build());
        }
        return RestResp.ok(list);
    }

    @Override
    public RestResp<PageRespDto<AdminInfoRespDto>> getAdminInfo(AdminPageReqDto adminPageReqDto) {
        Page<Admin> page = new Page<>();

        page.setCurrent(adminPageReqDto.getPageNum());
        page.setSize(adminPageReqDto.getPageSize());

        // 根据条件查询
        LambdaQueryWrapper<Admin> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Admin::getType, adminPageReqDto.getBackendType());
        lambdaQueryWrapper.like(adminPageReqDto.getName() != null,Admin::getName, adminPageReqDto.getName());

        // 分页查询
        IPage<Admin> adminListPage = adminMapper.selectPage(page, lambdaQueryWrapper);

        // 设置时间对象，用于格式化时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        List<AdminInfoRespDto> adminInfoRespDtoList = adminListPage.getRecords().stream().map(v -> AdminInfoRespDto.builder()
                .id(v.getId())
                .name(v.getName())
                .type(v.getType())
                .username(v.getUsername())
                .password(v.getPassword())
                .createUser(v.getCreateUser())
                .updateTime(format.format(v.getUpdateTime()))
                .build()).toList();

        return RestResp.ok(PageRespDto.of(adminPageReqDto.getPageNum(), adminPageReqDto.getPageSize(), page.getTotal(),adminInfoRespDtoList));
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestResp<Void> addAdmin(Admin admin) {
        LambdaQueryWrapper<Admin> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Admin::getUsername, admin.getUsername());

        Admin admins = adminMapper.selectOne(lambdaQueryWrapper);
        if (admins != null) {
            return RestResp.fail(ErrorCodeEnum.USER_NAME_EXIST);
        }

        adminMapper.insert(admin);
        return RestResp.ok();
    }

    @Override
    public RestResp<Admin> showAdminById(Long id) {
        Admin admin = adminMapper.selectById(id);
        return RestResp.ok(Admin.builder()
                .id(admin.getId())
                .name(admin.getName())
                .type(admin.getType())
                .username(admin.getUsername())
                .build());
    }

    @Override
    public RestResp<Void> updateAdmin(Admin admin) {
        LambdaQueryWrapper<Admin> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Admin::getId, admin.getId());
        Admin admins1 = adminMapper.selectOne(lambdaQueryWrapper);

        LambdaQueryWrapper<Admin> queryWrapper  = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getUsername, admin.getUsername());
        Admin admins2 = adminMapper.selectOne(queryWrapper);

        if (!Objects.equals(admins2.getUsername(), admin.getUsername())) {
            if (Objects.equals(admins1.getUsername(), admin.getUsername())) {
                return RestResp.fail(ErrorCodeEnum.USER_NAME_EXIST);
            }
        }

        adminMapper.updateById(admin);

        return RestResp.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestResp<Void> deleteAdminById(Long id) {
        adminMapper.deleteById(id);
        return RestResp.ok();
    }

    @Override
    public RestResp<PageRespDto<AuthorInfoRespDto>> getAuthorList(AuthorInfoReqDto authorInfoReqDto){
        Page<AuthorInfo> page = new Page<>();

        page.setCurrent(authorInfoReqDto.getPageNum());
        page.setSize(authorInfoReqDto.getPageSize());
        // 根据条件查询
        LambdaQueryWrapper<AuthorInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();


        lambdaQueryWrapper.like(authorInfoReqDto.getName() != null, AuthorInfo::getPenName, authorInfoReqDto.getName());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        // 分页查询
        IPage<AuthorInfo> authorInfoList = authorInfoMapper.selectPage(page, lambdaQueryWrapper);
        List<AuthorInfoRespDto> adminInfoRespDtoList = authorInfoList.getRecords().stream().map(v -> AuthorInfoRespDto.builder()
                .id(v.getId())
                .penName(v.getPenName())
                .telPhone(v.getTelPhone())
                .email(v.getEmail())
                .workDirection(v.getWorkDirection() == 0 ? "男频":"女频" )
                // 将LocalDateTime转为String对象
                .createTime(format.format(Date.from(v.getCreateTime().atZone(ZoneId.systemDefault()).toInstant())))
                .build()).toList();

        return RestResp.ok(PageRespDto.of(authorInfoReqDto.getPageNum(), authorInfoReqDto.getPageSize(), page.getTotal(),adminInfoRespDtoList));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestResp<Void> deleteAuthorById(Long id){
        authorInfoMapper.deleteById(id);
        return RestResp.ok();
    }

    @Override
    public RestResp<PageRespDto<UserInfoListRespDto>> getUserList(UserInfoReqDto userInfoReqDto) {
        Page<UserInfo> page = new Page<>();

        page.setCurrent(userInfoReqDto.getPageNum());
        page.setSize(userInfoReqDto.getPageSize());

        // 根据条件查询
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(userInfoReqDto.getName() != null, UserInfo::getNickName, userInfoReqDto.getName());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        // 分页查询
        IPage<UserInfo> userInfoList = userInfoMapper.selectPage(page, lambdaQueryWrapper);
        List<UserInfoListRespDto> userInfoRespDtoList = userInfoList.getRecords().stream().map(v-> UserInfoListRespDto.builder()
                .id(v.getId())
                .nickName(v.getNickName())
                .username(v.getUsername())
                .createTime(format.format(Date.from(v.getCreateTime().atZone(ZoneId.systemDefault()).toInstant())))
                .build()).toList();
//        log.info("用户对象:{}", userInfoRespDtoList);
        return RestResp.ok(PageRespDto.of(userInfoReqDto.getPageNum(), userInfoReqDto.getPageSize(), page.getTotal(),userInfoRespDtoList));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestResp<Void> deleteUserById(Long id){
        userInfoMapper.deleteById(id);
        return RestResp.ok();
    }


    @Override
    public RestResp<PageRespDto<BookListRespDto>> getBookList(BookListRepDto bookListReqDto) {
        Page<BookInfo> page = new Page<>();
        page.setCurrent(bookListReqDto.getPageNum());
        page.setSize(bookListReqDto.getPageSize());
        // 根据条件查询
        LambdaQueryWrapper<BookInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BookInfo::getCategoryId, bookListReqDto.getCategoryId());
        lambdaQueryWrapper.like(bookListReqDto.getName() != null, BookInfo::getBookName, bookListReqDto.getName());

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        IPage<BookInfo> bookInfoList = bookInfoMapper.selectPage(page, lambdaQueryWrapper);

        List<BookListRespDto> bookListRespDtoList = bookInfoList.getRecords().stream().map(v -> BookListRespDto.builder()
                .id(v.getId())
                .bookName(v.getBookName())
                .authorName(v.getAuthorName())
                .score(v.getScore())
                .bookStatus(v.getBookStatus() == 0 ? "连载中" : "已完结")
                .visitCount(v.getVisitCount())
                .wordCount(v.getWordCount())
                .lastChapterName(v.getLastChapterName())
                .lastChapterUpdateTime(format.format(Date.from(v.getLastChapterUpdateTime().atZone(ZoneId.systemDefault()).toInstant())))
                .build()).toList();
        return RestResp.ok(PageRespDto.of(bookListReqDto.getPageNum(), bookListReqDto.getPageSize(), page.getTotal(), bookListRespDtoList));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestResp<Void> deleteBookById(Long id){
        bookInfoMapper.deleteById(id);
        return RestResp.ok();
    }
}